import { setCacheNameDetails, clientsClaim, skipWaiting } from 'workbox-core'
import { ExpirationPlugin } from 'workbox-expiration'
import { CacheableResponsePlugin } from 'workbox-cacheable-response'
import { BackgroundSyncPlugin } from 'workbox-background-sync'
import { precacheAndRoute } from 'workbox-precaching/precacheAndRoute'
import { createHandlerBoundToURL } from 'workbox-precaching'
import { NavigationRoute, registerRoute, setDefaultHandler } from 'workbox-routing'
import { StaleWhileRevalidate, NetworkOnly, CacheFirst, NetworkFirst } from 'workbox-strategies'
import { addPostEventListener } from '@/workbox/sw-post'
import Dexie from 'dexie'
import { config } from '@/config/config'

/**
 * 缓存信息
 */
const sw_version = 'v1.0.4'
const db_version = config.version
// 设置缓存名称
setCacheNameDetails({
  prefix: 'app',
  suffix: sw_version
})

// 更新时自动生效,触发activate;
clientsClaim()
// 预缓存文件，self.__WB_MANIFEST是workbox生成的文件地址数组，项目中打包生成的所有静态文件都会自动添加到里面
precacheAndRoute(self.__WB_MANIFEST || [])

/**
 * 缓存策略
 * Cache First： 先缓存,失败访问网络;
 * Network First: 先访问网络,失败后访问缓存;
 * StaleWhileRevalidate：从缓存中读取资源的同时发送网络请求更新本地缓存
 * 不在同一域下的任何资源，不能使用 Cache only 和 Cache first。
 */


// 单页应用需要应用NavigationRoute进行缓存，此处可自定义白名单和黑名单
const url = ['redirect', 'homework', 'wq-book', 'learning', 'exercise', 'contact','dict']
url.forEach(u => {
  try {
    const handler = createHandlerBoundToURL(`${u}.html`)
    const navigationRoute = new NavigationRoute(handler, {
      denylist: []
    })
    registerRoute(navigationRoute, new CacheFirst({
      cacheName: 'html-cache-' + sw_version,
      plugins: [
        new CacheableResponsePlugin({ statuses: [0, 200] }),  // 请求成功才缓存
        new ExpirationPlugin({
          maxEntries: 60,
          maxAgeSeconds: 60 * 24 * 60 * 60 // 设置缓存有效期为60天
        })
      ]
    }))
  } catch (e) {
    console.log(e)
  }
})
// 缓存web的css资源
registerRoute(
  // Cache CSS files
  /.*\.css/,
  // 使用缓存，但尽快在后台更新
  new CacheFirst({
    // 使用自定义缓存名称
    cacheName: 'css-cache-' + sw_version,
    plugins: [
      new CacheableResponsePlugin({ statuses: [0, 200] }),  // 请求成功才缓存
      new ExpirationPlugin({
        maxEntries: 60,
        maxAgeSeconds: 60 * 24 * 60 * 60 // 设置缓存有效期为60天
      })
    ]
  })
)

// 缓存web的js资源
registerRoute(
  // 缓存JS文件
  /.*\.js$/,
  // 使用缓存，但尽快在后台更新
  new CacheFirst({
    // 使用自定义缓存名称
    cacheName: 'js-cache-' + sw_version,
    plugins: [
      new CacheableResponsePlugin({ statuses: [0, 200] }),  // 请求成功才缓存
      new ExpirationPlugin({
        maxEntries: 60,
        maxAgeSeconds: 60 * 24 * 60 * 60 // 设置缓存有效期为60天
      })
    ]
  })
)

// 缓存静态资源
registerRoute(
  /\.(?:png|gif|jpg|jpeg|svg|json|ttf|eot|woff|woff2)$/,
  new CacheFirst({
    cacheName: 'static-cache-' + sw_version,
    plugins: [
      new CacheableResponsePlugin({ statuses: [0, 200] }),  // 请求成功才缓存
      new ExpirationPlugin({
        maxEntries: 60,
        maxAgeSeconds: 60 * 24 * 60 * 60 // 设置缓存有效期为60天
      })
    ]
  })
)
//静态文件cdn地址-文件太大导致缓存上限
// registerRoute(/^https:\/\/ai-zj.oss-cn-shenzhen.aliyuncs.com\//, new CacheFirst({
//   cacheName: 'static-cdn-cache-' + sw_version,
//   plugins: [
//     new CacheableResponsePlugin({ statuses: [0, 200] }),  // 请求成功才缓存
//     new ExpirationPlugin({
//       maxEntries: 60,
//       maxAgeSeconds: 60 * 24 * 60 * 60 // 设置缓存有效期为60天
//     })
//   ]
// }))
//图片cdn地址，属于跨域资源，我们使用StaleWhileRevalidate缓存策略
registerRoute(/^https:\/\/img.xkw.com\//, new CacheFirst({
  cacheName: 'image-cdn-cache-' + sw_version,
  plugins: [
    new CacheableResponsePlugin({ statuses: [0, 200] }),  // 请求成功才缓存
    new ExpirationPlugin({
      maxEntries: 60,
      maxAgeSeconds: 60 * 24 * 60 * 60 // 设置缓存有效期为60天
    })
  ]
}))

// 接口数据使用服务端数据-正式环境
registerRoute(/^https:\/\/aizj.sndtech.cn\//, new NetworkFirst({
  cacheName: 'api-cache-' + sw_version,
  networkTimeoutSeconds: 1,
  plugins: [
    new CacheableResponsePlugin({ statuses: [0, 200] }),  // 请求成功才缓存
    new ExpirationPlugin({
      maxEntries: 60,
      maxAgeSeconds: 30 * 24 * 60 * 60 // 设置缓存有效期为30天
    })
  ]
}), 'GET')

// 接口数据使用服务端数据-演示环境
registerRoute(/^https:\/\/aizjtest.sndtech.cn\//, new NetworkFirst({
  cacheName: 'api-test-cache-' + sw_version,
  networkTimeoutSeconds: 1,
  plugins: [
    new CacheableResponsePlugin({ statuses: [0, 200] }),  // 请求成功才缓存
    new ExpirationPlugin({
      maxEntries: 60,
      maxAgeSeconds: 30 * 24 * 60 * 60 // 设置缓存有效期为30天
    })
  ]
}), 'GET')

// 接口数据使用服务端数据-开发环境
registerRoute(/^https:\/\/xuxin.natappvip.cc\//, new NetworkFirst({
  cacheName: 'api-dev-cache-' + sw_version,
  networkTimeoutSeconds: 1,
  plugins: [
    new CacheableResponsePlugin({ statuses: [0, 200] }),  // 请求成功才缓存
    new ExpirationPlugin({
      maxEntries: 60,
      maxAgeSeconds: 30 * 24 * 60 * 60 // 设置缓存有效期为30天
    })
  ]
}), 'GET')

// setDefaultHandler(
//   new NetworkFirst({
//     cacheName: 'default-cache-'+version,
//   })
// );


const deleteCache = async (key) => {
  await caches.delete(key)
}

const deleteOldCaches = async () => {
  const exp = new RegExp(sw_version, 'g')
  const keyList = await caches.keys()
  const cachesToDelete = keyList.filter((key) => !exp.test(key))
  const db = new Dexie('post_cache')
  db.delete()
  await Promise.all(cachesToDelete.map(deleteCache))
}

// 只有sw文件修改才会重新安装,当旧版本不在使用sw才会触发激活;
addEventListener('activate', (event) => {
  console.log('service worker(activate) 激活完成.')
  event.waitUntil(deleteOldCaches())
})

// service worker通过message和主线程通讯
addEventListener('message', event => {
  const replyPort = event.ports[0]
  const message = event.data
  console.log('service worker 监听message')
  if (replyPort && message && message.type === 'skip-waiting') {
    event.waitUntil(
      skipWaiting()
    )
  }
})

addPostEventListener(db_version)
